package com.migu.rbac.util;

import com.alibaba.fastjson.JSONObject;
import com.migu.rbac.RbacConstant;
import com.migu.rbac.model.SysRole;
import com.migu.rbac.model.SysUser;
import com.migu.rbac.repository.SysUserRepository;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class TokenProvider {
    @Value("${security.jwt.secret-key}")
    private String secretKey;
    @Value("${security.jwt.expiration}")
    private long expiration;
    @Autowired
    private SysUserRepository userRepository;

    public static final String CLAIM_KEY_ISSUER = "iss";
    public static final String CLAIM_KEY_ISSUED_AT = "iat";
    public static final String CLAIM_KEY_SUBJECT = "sub";
    public static final String CLAIM_KEY_USER_ID = "user_id";
    public static final String CLAIM_KEY_USER_NAME = "user_name";
    public static final String CLAIM_KEY_REFRESH_TIMES = "refresh_times";

    private Logger log = LoggerFactory.getLogger(TokenProvider.class);

    /**
     * 解析乐高token
     * @param request request
     * @return
     */
    public com.migu.rbac.domain.User getUserInfo(HttpServletRequest request) {
        String userStr = request.getHeader(RbacConstant.Common.SSO_USER);
        return this.getUserInfo(userStr);
    }

    /**
     * 解析乐高token
     * @param userStr H5传入的User字符串
     * @return
     */
    public com.migu.rbac.domain.User getUserInfo(String userStr) {
        String encode = Escape.unescape(userStr);
        try {
            return JSONObject.parseObject(encode, com.migu.rbac.domain.User.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public Authentication getAuthentivationByNoms(com.migu.rbac.domain.User user) {

        //根据用户名查找角色
        SysUser byloginName = userRepository.findByloginName(user.getLoginName());
        if (null == byloginName) {
            // 将乐高的用户插入用户表
            SysUser sysUser = new SysUser();
            sysUser.setLoginname(user.getLoginName());
            sysUser.setPassword(user.getLoginName());
            sysUser.setUsername(user.getUserName());
            sysUser.setRoles(new ArrayList<>());
            userRepository.saveUser(sysUser);
            byloginName = sysUser;
        }

        Collection<? extends GrantedAuthority> authorities =
                byloginName == null ? new ArrayList<>() :
                        byloginName.getRoles()
                                   .stream()
                                   .map(e -> new SimpleGrantedAuthority(e.getRolename()))
                                   .collect(Collectors.toList());

        User principal = new User(user.getUserName(), "", authorities);
        return new UsernamePasswordAuthenticationToken(principal, user.getNewtoken(), authorities);
    }


    //通过
    public Authentication getAuthentication(String token) {
        log.info("getAuthentication");
        Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
        if (claims != null) {
            String user_name = claims.get(CLAIM_KEY_USER_NAME).toString();
            //根据用户名查找角色
            SysUser byloginName = userRepository.findByloginName(user_name);
            Collection<? extends GrantedAuthority> authorities =
                    byloginName == null ? new ArrayList<>() :
                            byloginName.getRoles()
                                       .stream()
                                       .map(e -> new SimpleGrantedAuthority(e.getRolename()))
                                       .collect(Collectors.toList());
            log.info("Subject:" + claims.getSubject());
            User principal = new User(claims.getSubject(), "", authorities);
            return new UsernamePasswordAuthenticationToken(principal, token, authorities);
        }
        return null;
    }

    private Collection<? extends GrantedAuthority> getAuthorities(List<SysRole> roles) {
        //List<String> collect1 = roles.stream().map(e -> e.getRolename()).collect(Collectors.toList());
        List<GrantedAuthority> auths = new ArrayList<>();
        for (SysRole role : roles) {
            auths.add(new SimpleGrantedAuthority(role.getRolename()));
        }
        return auths;
    }

    //解析JWT
    public Claims parseToken(String token) {
        boolean isValidToken = validateToken(token);
        if (isValidToken) {
            return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
        } else {
            return null;
        }
    }

    //验证JWT是否合法
    public boolean validateToken(String token) {
        try {
            Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            return true;
        } catch (SignatureException e) {
            log.info("Invalid JWT signature.");
            log.trace("Invalid JWT signature trace: {}", e);
        } catch (MalformedJwtException e) {
            log.info("Invalid JWT token.");
            log.trace("Invalid JWT token trace: {}", e);
        } catch (ExpiredJwtException e) {
            log.info("Expired JWT token.");
            log.trace("Expired JWT token trace: {}", e);
        } catch (UnsupportedJwtException e) {
            log.info("Unsupported JWT token.");
            log.trace("Unsupported JWT token trace: {}", e);
        } catch (IllegalArgumentException e) {
            log.info("JWT token compact of handler are invalid.");
            log.trace("JWT token compact of handler are invalid trace: {}", e);
        }
        return false;
    }

    //创建JWT
    public String createToken(String userID, String userName, int refreshTimes) {
        long now = (new Date()).getTime();
        Date validity = new Date(now + this.expiration);
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put(CLAIM_KEY_ISSUER, "EYE-INSIGHT");
        claims.put(CLAIM_KEY_ISSUED_AT, System.currentTimeMillis());
        claims.put(CLAIM_KEY_SUBJECT, userID);
        claims.put(CLAIM_KEY_USER_ID, userID);
        claims.put(CLAIM_KEY_USER_NAME, userName);
        claims.put(CLAIM_KEY_REFRESH_TIMES, refreshTimes);
        return Jwts.builder().signWith(SignatureAlgorithm.HS512, secretKey).setClaims(claims).setExpiration(validity).compact();
    }

    public static void main(String[] args) {
        //Date date = new Date();
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //Date date2 = new Date((new Date()).getTime() + 43200000);
        //System.out.println(sdf.format(date));
        //System.out.println(sdf.format(date2));

        //Response response = new Response();
        //response.setIsSuccess(true);
        //if (null == null || !response.getIsSuccess()) {
        //    System.out.println("1222222222222222");
        //}

        String userStr = new String("%7B%22userName%22%3A%22%u5218%u6D77%u658C%22%2C%22newtoken%22%3A%22eyJhbGciOiJIUzUxMiJ9.eyJyZWZyZXNoX3RpbWVzIjowLCJzdWIiOiJlZmYzNzdjZTgxYzM0YjRjODMwNzU1YjczMDcwOTFmOCIsImxvZ2luX25hbWUiOiJsaXVoYWliaW4iLCJ1c2VyX2lkIjoiZWZmMzc3Y2U4MWMzNGI0YzgzMDc1NWI3MzA3MDkxZjgiLCJ1c2VyX25hbWUiOiLliJjmtbfmlowiLCJpc3MiOiJQT1JUQUwiLCJ1c2VyX3JvbGVzIjoiUk9MRV9VU0VSIiwidXNlcl9tb2R1bGVzIjoiQVBQLTAwMSxBUFAtMDAyLEFQUC0wMDkiLCJleHAiOjE1NTc3NzM1MjksImlhdCI6MTU1Nzc0NDcyOTAwMSwidXNlcl9wcml2aWxlZ2UiOiJwcml2aWxlZ2UtMDEifQ.OeDvnz6T5RSR72MUzPUCMJzjthKSEPxmGHTUuTKYOP-cJNC8xOmwhQlTR2poWu-1mdtPdYQXP_lsRnaAw863GA%22%2C%22userRoles%22%3A%22ROLE_USER%22%2C%22userPrivileges%22%3A%22privilege-01%22%2C%22loginName%22%3A%22liuhaibin%22%7D");
        try {

            String unescape = Escape.unescape(userStr);
            System.out.println(unescape);
            String s = "eyJhbGciOiJIUzUxMiJ9.eyJyZWZyZXNoX3RpbWVzIjowLCJzdWIiOiJlZmYzNzdjZTgxYzM0YjRjODMwNzU1YjczMDcwOTFmOCIsImxvZ2luX25hbWUiOiJsaXVoYWliaW4iLCJ1c2VyX2lkIjoiZWZmMzc3Y2U4MWMzNGI0YzgzMDc1NWI3MzA3MDkxZjgiLCJ1c2VyX25hbWUiOiLliJjmtbfmlowiLCJpc3MiOiJQT1JUQUwiLCJ1c2VyX3JvbGVzIjoiUk9MRV9VU0VSIiwidXNlcl9tb2R1bGVzIjoiQVBQLTAwMSxBUFAtMDAyLEFQUC0wMDkiLCJleHAiOjE1NTc3NzM1MjksImlhdCI6MTU1Nzc0NDcyOTAwMSwidXNlcl9wcml2aWxlZ2UiOiJwcml2aWxlZ2UtMDEifQ.OeDvnz6T5RSR72MUzPUCMJzjthKSEPxmGHTUuTKYOP-cJNC8xOmwhQlTR2poWu-1mdtPdYQXP_lsRnaAw863GA";
            com.migu.rbac.domain.User user = JSONObject.parseObject(unescape, com.migu.rbac.domain.User.class);
            System.out.println(s.equals(user.getNewtoken()));
        } catch (Exception e) {
            System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>EEEEEEEEEEEEEEEE");
            e.printStackTrace();
        }
    }
}
